#pragma once
#include <boost/type_traits/is_fundamental.hpp>

namespace catan
{
	struct SerializerDirection
	{
		enum Enum
		{
			In = 0,
			Out,
		};
	};

	template <class Type, SerializerDirection::Enum isOut>
	class SerializerTmpl
	{
	public:
		template <class ValueType>
		SerializerTmpl& operator & (ValueType& t) 
		{
			return this->SerialToStream(t); 
		}

		virtual bool IsOut() { return isOut;}

		Type& GetStringStream() { return mStringStream; }

		template <class ValueType>
		SerializerTmpl& SerialToStream(ValueType& t, Int2Type<SerializerDirection::Out>, Int2Type<true>)
		{
			//mStringStream << t;
			mStringStream.write((const char*)&t, sizeof(Type));
			return *this;
		}

		template <class ValueType>
		SerializerTmpl& SerialToStream(ValueType& t, Int2Type<SerializerDirection::In>, Int2Type<true>)
		{
			mStringStream.read((char*)&t, sizeof(Type));
			return *this;
		}

		template <class ValueType>
		SerializerTmpl& SerialToStream(std::vector<ValueType>& t, Int2Type<SerializerDirection::Out>, Int2Type<false>)
		{
			//(*this)& t.size();
			this->SerialToStream(t);
			for (typename std::vector<ValueType>::iterator it(t.begin());
				it != t.end(); ++it)
			{
				(*this) & *it;
			}
			return *this;
		}

		template <class ValueType>
		SerializerTmpl& SerialToStream(std::vector<ValueType>& t, Int2Type<SerializerDirection::In>, Int2Type<false>)
		{
			mStringStream.read((char*)&t, sizeof(Type));
			return *this;
		}

		template <class ValueType>
		SerializerTmpl& SerialToStream(ValueType& t)
		{
			return SerialToStream(t, Int2Type<isOut>(), Int2Type<boost::is_fundamental<ValueType>::value>());
		}

		tstring Str() { return mStringStream.str();}
// 		virtual Serializer& Serial(int& t) { return SerialToStream(t);}
// 		virtual Serializer& Serial(bool& t) { return SerialToStream(t);}

		Type mStringStream;
		
	};

	//SerializerTmpl<tstringstream, true> so;
	//SerializerTmpl<std::istringstream, false> si;
}	